package com.gemini.main.tablestore;

import com.alicloud.openservices.tablestore.SyncClient;
import com.alicloud.openservices.tablestore.model.search.SearchQuery;
import com.alicloud.openservices.tablestore.model.search.SearchRequest;
import com.alicloud.openservices.tablestore.model.search.SearchResponse;
import com.alicloud.openservices.tablestore.model.search.agg.AggregationBuilders;
import com.alicloud.openservices.tablestore.model.search.agg.AggregationResults;
import com.alicloud.openservices.tablestore.model.search.groupby.*;
import com.alicloud.openservices.tablestore.model.search.query.QueryBuilders;

/**
 * gemini
 * com.gemini.main.tablestore.AggregationSample
 *
 * @author zhanghailin
 */
public class AggregationSample {

    /**
     * 所有商品中每一个类别各有多少个？且统计每一个类别的价格最大值和最小值。
     * 返回结果举例："水果：5个（其中价格最贵15元，最便宜3元），洗漱用品：10个（其中价格最贵98元，最便宜1元），电子设备：3个（其中价格最贵8699元，最便宜2300元），其它：15个（其中价格最贵1000
     * 元，最便宜80元）"
     */
    public void groupByField(SyncClient client) {
        // 构建查询语句
        SearchRequest searchRequest = SearchRequest.newBuilder()
                .tableName("tableName")
                .indexName("indexName")
                .searchQuery(
                        SearchQuery.newBuilder()
                                .query(QueryBuilders.matchAll())
                                .limit(0)
                                .addGroupBy(GroupByBuilders
                                        .groupByField("name1", "column_type")
                                        .addSubAggregation(AggregationBuilders.min("subName1", "column_price"))
                                        .addSubAggregation(AggregationBuilders.max("subName2", "column_price"))
                                )
                                .build())
                .build();
        //执行查询
        SearchResponse resp = client.search(searchRequest);
        //获取统计聚合的结果
        for (GroupByFieldResultItem item : resp.getGroupByResults().getAsGroupByFieldResult("name1").getGroupByFieldResultItems()) {
            // 值
            System.out.println(item.getKey());
            // 个数
            System.out.println(item.getRowCount());
            // 最低价格
            System.out.println(item.getSubAggregationResults().getAsMinAggregationResult("subName1").getValue());
            // 最高价格
            System.out.println(item.getSubAggregationResults().getAsMaxAggregationResult("subName2").getValue());
        }
    }

    /**
     * 求商品销量时候按[0,1k)、[1k，5k)、[5k,正无穷)进行分组计算每个范围的销量。
     */
    public void groupByRange(SyncClient client) {
        // 构建查询语句
        SearchRequest searchRequest = SearchRequest.newBuilder()
                .tableName("tableName")
                .indexName("indexName")
                .searchQuery(
                        SearchQuery.newBuilder()
                                .query(QueryBuilders.matchAll())
                                .limit(0)
                                .addGroupBy(
                                        GroupByBuilders.groupByRange("name1", "column_number")
                                                //.groupByRange("name1", "column_number")
                                                .addRange(0, 1000)
                                                .addRange(1000, 5000)
                                                .addRange(5000, Double.MAX_VALUE)
                                )
                                .build())
                .build();
        //执行查询
        SearchResponse resp = client.search(searchRequest);
        //获取统计聚合的结果
        for (GroupByRangeResultItem item : resp.getGroupByResults().getAsGroupByRangeResult("name1").getGroupByRangeResultItems()) {
            // 范围
            System.out.println(item.getKey());
            // 个数
            System.out.println(item.getRowCount());
        }
    }

    /**
     * 求距离万达广场[0,1000米)、[1000米，5000米)、[5000米,正无穷)每个范围的人数。
     */
    public void groupByGeoDistance(SyncClient client) {
        // 构建查询语句
        SearchRequest searchRequest = SearchRequest.newBuilder()
                .tableName("tableName")
                .indexName("indexName")
                .searchQuery(
                        SearchQuery.newBuilder()
                                .query(QueryBuilders.matchAll())
                                .limit(0)
                                .addGroupBy(GroupByBuilders
                                        .groupByGeoDistance("name1", "column_geo_point")
                                        .origin(3.1, 6.5)
                                        .addRange(0, 1000)
                                        .addRange(1000, 5000)
                                        .addRange(5000, Double.MAX_VALUE)
                                )
                                .build())
                .build();
        //执行查询
        SearchResponse resp = client.search(searchRequest);
        //获取统计聚合的结果
        for (GroupByGeoDistanceResultItem item : resp.getGroupByResults().getAsGroupByGeoDistanceResult("name1").getGroupByGeoDistanceResultItems()) {
            // 范围
            System.out.println(item.getKey());
            // 个数
            System.out.println(item.getRowCount());
        }
    }

    /**
     * 按照Filter（即Query）进行分组，例如添加三个Filter（销量大于100、产地是浙江、描述中包含浙江关键词），然后获得每个Filter匹配到的数量。
     */
    public void groupByFilter(SyncClient client) {
        // 构建查询语句
        SearchRequest searchRequest = SearchRequest.newBuilder()
                .tableName("tableName")
                .indexName("indexName")
                .searchQuery(
                        SearchQuery.newBuilder()
                                .query(QueryBuilders.matchAll())
                                .limit(0)
                                .addGroupBy(GroupByBuilders
                                        .groupByFilter("name1")
                                        .addFilter(QueryBuilders.range("number").greaterThanOrEqual(100))
                                        .addFilter(QueryBuilders.term("place","浙江省"))
                                        .addFilter(QueryBuilders.match("text","杭州"))
                                )
                                .build())
                .build();
        //执行查询
        SearchResponse resp = client.search(searchRequest);
        //获取统计聚合的结果, 按照addFilter的顺序。
        for (GroupByFilterResultItem item : resp.getGroupByResults().getAsGroupByFilterResult("name1").getGroupByFilterResultItems()) {
            // 个数
            System.out.println(item.getRowCount());
        }
    }

    public void multipleGroupBy(SyncClient client) {
        // 构建查询语句
        SearchRequest searchRequest = SearchRequest.newBuilder()
                .tableName("tableName")
                .indexName("indexName")
                .searchQuery(
                        SearchQuery.newBuilder()
                                .query(QueryBuilders.matchAll())
                                .limit(0)
                                .addAggregation(AggregationBuilders.min("name1", "long"))
                                .addAggregation(AggregationBuilders.sum("name2", "long"))
                                .addAggregation(AggregationBuilders.distinctCount("name3", "long"))
                                .addGroupBy(GroupByBuilders.groupByField("name4", "type"))
                                .addGroupBy(GroupByBuilders.groupByRange("name5", "long").addRange(1, 15))
                                .build())
                .build();
        //执行查询
        SearchResponse resp = client.search(searchRequest);
        //获取第1个统计聚合的结果
        System.out.println(resp.getAggregationResults().getAsMinAggregationResult("name1").getValue());
        //获取第2个统计聚合的结果
        System.out.println(resp.getAggregationResults().getAsSumAggregationResult("name2").getValue());
        //获取第3个统计聚合的结果
        System.out.println(resp.getAggregationResults().getAsDistinctCountAggregationResult("name3").getValue());
        //获取第4个统计聚合的结果
        for (GroupByFieldResultItem item : resp.getGroupByResults().getAsGroupByFieldResult("name4").getGroupByFieldResultItems()) {
            // key
            System.out.println(item.getKey());
            // 个数
            System.out.println(item.getRowCount());
        }
        //获取第5个统计聚合的结果
        for (GroupByRangeResultItem item : resp.getGroupByResults().getAsGroupByRangeResult("name4").getGroupByRangeResultItems()) {
            // 个数
            System.out.println(item.getRowCount());
        }
    }

    /**
     * 嵌套的统计聚合示例：外层2个Aggregation和1个GroupByField，GroupByField中又添加了2个Aggregation和1个GroupByRange
     */
    public void subGroupBy(SyncClient client) {
        // 构建查询语句
        SearchRequest searchRequest = SearchRequest.newBuilder()
                .indexName("index_name")
                .tableName("table_name")
                .returnAllColumns(true)
                .searchQuery(
                        SearchQuery.newBuilder()
                                .query(QueryBuilders.match("textField", "hello"))
                                .limit(10)
                                .addAggregation(AggregationBuilders.min("name1", "fieldName1"))
                                .addAggregation(AggregationBuilders.max("name2", "fieldName2"))
                                .addGroupBy(GroupByBuilders
                                        .groupByField("name3", "fieldName3")
                                        .addSubAggregation(AggregationBuilders.max("subName1", "fieldName4"))
                                        .addSubAggregation(AggregationBuilders.sum("subName2", "fieldName5"))
                                        .addSubGroupBy(GroupByBuilders
                                                .groupByRange("subName3", "fieldName6")
                                                .addRange(12, 90)
                                                .addRange(100, 900)
                                        ))
                                .build())
                .build();
        //执行查询
        SearchResponse resp = client.search(searchRequest);
        //第一层的agg结果
        AggregationResults aggResults = resp.getAggregationResults();
        System.out.println(aggResults.getAsMinAggregationResult("name1").getValue());
        System.out.println(aggResults.getAsMaxAggregationResult("name2").getValue());

        //取出第一层的groupByField结果，并同时取出其嵌套的agg结果
        GroupByFieldResult results = resp.getGroupByResults().getAsGroupByFieldResult("someName1");
        for (GroupByFieldResultItem item : results.getGroupByFieldResultItems()) {
            System.out.println("数量：" + item.getRowCount());
            System.out.println("key：" + item.getKey());

            //取出sub统计聚合的结果
            //SubAggregation: min 的结果
            System.out.println(item.getSubAggregationResults().getAsMaxAggregationResult("subName1"));
            //SubAggregation: max 的结果
            System.out.println(item.getSubAggregationResults().getAsSumAggregationResult("subName2"));
            //SubGroupBy: GroupByRange 的结果
            GroupByRangeResult subResults = resp.getGroupByResults().getAsGroupByRangeResult("subName3");
            for (GroupByRangeResultItem subItem : subResults.getGroupByRangeResultItems()) {
                System.out.println("数量：" + subItem.getRowCount());
                System.out.println("key：" + subItem.getKey());
            }
        }
    }
}
